// Node引入包名
const iot = require('alibabacloud-iot-device-sdk');
const WebSocket = require('ws');

//记录客户端
const webSocketClients = {}

//iot设备状态
const deviceClients = {}

// CONNECT /:userID
// wscat -c ws://localhost:5000/1

//wobsockt 实现数据实时刷新
var wss
function initWs(server) {
	wss = new WebSocket.Server({ port: 3002 });
	wss.on('connection', (ws, req) => {
	  //记录客户端
	  var userID = req.url.substr(1)
	  webSocketClients[userID] = ws
	  console.log('ws connected ' + userID + ' in ' + Object.getOwnPropertyNames(webSocketClients))
	  
	  // ws.on('message', (message) => {
	  //   console.log(`Received message => ${message}`);
	  // });
	  
	  ws.on('close', (message) => {
	    console.log('ws close ' + userID);
		delete webSocketClients[userID]
	  });
	});
}

function sendWsClient(clientId, msg) {
	if (!wss) {
		return
	}
	var client = webSocketClients[clientId]
	if (!client) {
		console.log(`not find ws client: ${clientId}`)
		return
	}
	
	if (client.readyState === WebSocket.OPEN) {
		console.log(`ws send ${clientId}: ${msg}`)
		client.send(msg);
	}
}

//连接设备
function connect(deviceList, wsClientId) {
	if (!deviceList) {
		console.log("iotClient#online : deviceList empty!")
		return
	}
	for (let item of deviceList) {
      let deviceId = item.pk + "#" + item.dn
	  // 连接已存在
	  if (deviceClients[deviceId]) {
		  continue;
	  }
	  console.log("connect device pk: %s, dn: %s, secret: %s", item.pk, item.dn, item.ds);
	  const device = iot.device({
	    productKey: item.pk,
	    deviceName: item.dn,
	    deviceSecret: item.ds,
	    regionId: 'cn-shanghai'
	  });
	  
	  device.on('connect', () => {
	    console.log('%s#%s connect successfully!', item.pk, item.dn);
		deviceClients[deviceId] = device
	  })
	  
	  device.on("offline", () => {
	    console.log('%s#%s offline!', item.pk, item.dn);
	  })
	  
	  device.on("close", () => {
	    console.log('%s#%s close!', item.pk, item.dn);
	  		delete deviceClients[deviceId]
	  })
	  
	  device.onService('generalService', function (res,reply) {
	    console.log('generalService called,res:',res);
		let notifyJson = JSON.stringify({dn:item.dn, action: 'generalService called', message: JSON.stringify(res), time: Date.now()});
		sendWsClient(wsClientId, notifyJson)
	    //reply(""); //返回处理结果
	  });
	}
}

//设备断开连接
function disconnect(deviceList) {
	if (!deviceList) {
		console.log("iotClient#online : deviceList empty!")
		return
	}
	for (let item of deviceList) {
      let deviceId = item.pk + "#" + item.dn
	  console.log("disconnect device pk: %s, dn: %s", item.pk, item.dn);
	  // 连接存在
	  if (deviceClients[deviceId]) {
	      deviceClients[deviceId].end()
	  }
	}
}

// 是否在线
function connected(deviceList) {
	let ret = []
	for (let item of deviceList) {
		let deviceId = item.pk + "#" + item.dn
		let deviceClient = deviceClients[deviceId]
		if (deviceClient && deviceClient.connected) {
			ret.push({"pk":item.pk, "dn":item.dn, "on":true})
		} else{
			ret.push({"pk":item.pk, "dn":item.dn, "on":false})
		}
	}
	return ret
}

//上报事件
function reportGeneralEvent(deviceList, eventName, eventData, wsClientId) {
	if (!deviceList) {
		console.log("iotClient#reportEvent : deviceList empty!")
		return ret
	}
	for (let item of deviceList) {
		let deviceId = item.pk + "#" + item.dn
		let deviceClient = deviceClients[deviceId]
		if (deviceClient) {
			console.log("iotClient#reportEvent : generalEvent, eventName: %s", eventName)
			let body = {
				dataArray: [{
					eventName:  eventName,
					data: replacePlaceholders(eventData, item),
					}]
			}
			let callback = null;
			if(wsClientId) {
				callback = (err, res)=>{
					let fbJson, msg;
					msg = err ? err : res;
					fbJson = {dn:item.dn, action: `generalEvent: ${JSON.stringify(body)}`, message: JSON.stringify(msg), time: Date.now()};
					sendWsClient(wsClientId, JSON.stringify(fbJson))
				}
			}
			deviceClient.postEvent('generalEvent', body, callback);
		}
	}
}

//替换模板占位符${XXX}
function replacePlaceholders(templateStr, data) {
  return templateStr.replace(/\$\{(\w+)\}/g, (match, placeholder) => {
    return data[placeholder] !== undefined ? data[placeholder].toString() : match;
  });
}

// 导出方法
module.exports = {
	initWs,
    connect,
	disconnect,
	connected,
	reportGeneralEvent
};

